package devkit.commando.rpc {
	
	import devkit.commando.CommandBase;
	import devkit.commando.CommandManager;
	import devkit.commando.ICommand;
	
	import mx.rpc.AbstractOperation;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.remoting.mxml.RemoteObject;
	
	/**
	 * Base RPC command class that should be extended by all RPC command classes.
	 * @author Francois Dempers
	 */
	public class RPCBase extends CommandBase {
		
		/** The path to the service to connect to on the remote server. */
		private var serviceGateway:RPCGateway;
		
		/** The path to the service to connect to on the remote server. */
		private var servicePath:String;
		
		/**
		 * Creates a new <code>RPCBase</code> command.
		 * @param gateway The gateway to connect through.
		 * @param service The path to the service to invoke.
		 * @param resultHandler The function to invoke should a result be returned.
		 * @param faultHandler The client side function to invoke when a fault is received.
		 */
		public function RPCBase(gateway:RPCGateway, service:String, resultHandler:Function=null, faultHandler:Function=null) {
			
			super(resultHandler, faultHandler);
			serviceGateway = gateway;
			servicePath = service;
		}
		
		/**
		 * Invokes the server side function of the command passing a number of arguments.
		 * @param serviceFunction The server side function to invoke.
		 * @param ...args The arguments to pass to the server side function.
		 */
		protected function invoke(serviceFunction:String, ...args):void {
			
			call(serviceFunction, args);
		}
		
		/**
		 * Invokes the server side function of the command passing arguments in the form of an array.
		 * @param serviceFunction The server side function to invoke.
		 * @param args The arguments to pass to the server side function.
		 */
		protected function call(serviceFunction:String, args:Array):void {
			
			var service:RemoteObject = new RemoteObject();
			service.endpoint = serviceGateway.address;
			service.destination = serviceGateway.destination;
			service.source = servicePath;
			
			var op:AbstractOperation = service.getOperation(serviceFunction);
			op.arguments = args;
			
			if(op.hasEventListener(ResultEvent.RESULT) == false) {
				op.addEventListener(ResultEvent.RESULT, (this as ICommand).result, false, 0, true);
			}
			if(op.hasEventListener(FaultEvent.FAULT) == false) {
				op.addEventListener(FaultEvent.FAULT, (this as ICommand).fault, false, 0, true);				
			}
			op.send();
			
			CommandManager.processChain.addCommand(this);
		}
	}
}